package com.example.demo.config;

import com.example.demo.filter.JsonAuthenticationFilter;
import com.example.demo.filter.JwtAuthenticationTokenFilter;
import com.example.demo.filter.LogoutExceptionFilter;
import com.example.demo.handler.*;
import com.example.demo.mapper.UserMapper;
import com.example.demo.service.impl.CustomUserDetailServiceImpl;
import com.example.demo.utils.JwtUtil;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private UserMapper userMapper;
    @Resource
    private JwtUtil jwtUtil;

    @Bean
    public AuthenticationManager authenticationManager(
            AuthenticationConfiguration authConfig  // 注入Spring Security的配置
    ) throws Exception {
        return authConfig.getAuthenticationManager(); // 获取全局AuthenticationManager
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public UserDetailsService userDetailsService(){
        return new CustomUserDetailServiceImpl();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("http://localhost:8081"); // 允许的前端地址
        config.addAllowedOrigin("http://localhost:5173");
        config.addAllowedMethod("*"); // 允许所有 HTTP 方法
        config.addAllowedHeader("*"); // 允许所有请求头
        config.setAllowCredentials(true); // 允许携带凭证（如 Cookie）
        config.addExposedHeader("Token-Expired"); // 暴露响应头
        config.addExposedHeader("New-Token");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
        http.authorizeHttpRequests(res -> res
                        .requestMatchers(HttpMethod.POST, "/user/register").permitAll()
                        .requestMatchers("/user/logout").permitAll()
                        .requestMatchers("/user/login").permitAll()
                        .requestMatchers("/ws/**").permitAll()
                        .requestMatchers("/actuator").permitAll()
                        .anyRequest().authenticated()
                )
//                .formLogin(login -> login.loginProcessingUrl("/user/login")
//                        .successHandler(new MyAuthenticationSuccessHandler(stringRedisTemplate))
//                        .failureHandler(new MyAuthenticationFailureHandler()))
                .formLogin(AbstractHttpConfigurer::disable)
                .logout(logout -> logout.logoutUrl("/user/logout")
                        .addLogoutHandler(new MyLogoutHandler(stringRedisTemplate))
                        .clearAuthentication(true)
                        .logoutSuccessHandler(new MyLogoutSuccessHandler())
                        .permitAll())
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                .csrf(AbstractHttpConfigurer::disable)
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .addFilterBefore(new JwtAuthenticationTokenFilter(stringRedisTemplate, userMapper, jwtUtil), UsernamePasswordAuthenticationFilter.class)
                .addFilterAt(new JsonAuthenticationFilter(stringRedisTemplate, authenticationManager), UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(new LogoutExceptionFilter(), LogoutFilter.class);
        return http.build();
    }

}
